package transport.netty.server;

import codec.CommonDecoder;
import codec.CommonEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import provider.ServiceProvider;
import provider.ServiceProviderImpl;
import register.NacosServiceDisCovery;
import register.NacosServiceRegistry;
import register.ServiceDiscovery;
import register.ServiceRegister;
import serializer.Serializer;
import transport.AbstractRpcServer;
import transport.RpcServer;

import java.net.InetSocketAddress;

public class NettyServer extends AbstractRpcServer {
    private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);
    private ServerBootstrap serverBootstrap;
    private EventLoopGroup bossLoopGroup;
    private EventLoopGroup workerLoopGroup;

    private ServiceProvider serviceProvider;
    private ServiceRegister serviceRegister;

    private Serializer serializer;
    private final String host;
    private final int port;

    public NettyServer(String host, int port, Integer serializer) {
        this.host = host;
        this.port = port;
        //使用nacos 实现 服务注册
        this.serviceRegister = new NacosServiceRegistry();
        this.serviceProvider = new ServiceProviderImpl();
        this.serializer = Serializer.getBycode(serializer);
        //创建时 自动扫描服务进行注册
        scanServices();
    }

    //接口注册 与接口实现类添加
    @Override
    public void publishService(Object service, String serviceName) {
        //本地注册一个接口 以及一个实现类
        serviceProvider.addService(serviceName,service);
        //注册中心 注册 一个服务地址
        serviceRegister.registerService(serviceName,new InetSocketAddress(host,port));
        //启动服务
        start();
    }

    @Override
    public void start() {
        //启动服务器
        serverBootstrap = new ServerBootstrap();
        bossLoopGroup = new NioEventLoopGroup();
        workerLoopGroup = new NioEventLoopGroup();
        ChannelFuture future = serverBootstrap.group(bossLoopGroup, workerLoopGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                        ChannelPipeline pipeline = nioSocketChannel.pipeline();
                        pipeline
                                .addLast(new CommonDecoder())
                                .addLast(new CommonEncoder(serializer))
                                .addLast(new NettyServerHandler());
                    }
                }).bind(host, port);
        try {
            ChannelFuture channelFuture = future.sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            logger.error("服务器启动时有错误发生", e);
        } finally {
            bossLoopGroup.shutdownGracefully();
            workerLoopGroup.shutdownGracefully();
        }
    }


}
